
#include <stdio.h>
#include <stdlib.h>
#include <lua.h>
#include <lauxlib.h>
#include <lualib.h>
#include <sdl/sdl.h>
#include <png.h>
#include "guacimage.h"

// Parameters: FILE* pointer
// Returns: light userdata to SDL_Surface
int raw_loadpng(lua_State* L)
{
    FILE* fp = *(FILE**)lua_touserdata(L,1);

    png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);

    if (!png_ptr)
        luaL_error(L, "unable to allocate read struct");

    png_infop info_ptr = png_create_info_struct(png_ptr);
    if (!info_ptr)
    {
        png_destroy_read_struct(&png_ptr, (png_infopp)NULL, (png_infopp)NULL);
        return luaL_error(L, "unable to allocate info struct");
    }

    SDL_Surface* surf = NULL;

    if (setjmp(png_jmpbuf(png_ptr)))
    {
        png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL);
        if (surf)
            SDL_FreeSurface(surf);
        return luaL_error(L, "invalid PNG");
    }

    png_init_io(png_ptr, fp);

    png_set_sig_bytes(png_ptr, 0);

    png_read_info(png_ptr, info_ptr);

    int width = info_ptr->width;
    int height = info_ptr->height;

    png_set_expand(png_ptr);

    surf = SDL_CreateRGBSurface(SDL_SWSURFACE, width, height, 24,
        0x000000FF,
        0x0000FF00,
        0x00FF0000,
        0x00000000
    );

    if (SDL_MUSTLOCK(surf))
        SDL_LockSurface(surf);

    png_bytep rows[height];
    int i;
    for (i = 0; i < height; i++)
        rows[i] = surf->pixels + (surf->pitch * i);

    png_read_image(png_ptr, rows);

    png_read_end(png_ptr, NULL);

    if (SDL_MUSTLOCK(surf))
        SDL_UnlockSurface(surf);

    png_destroy_read_struct(&png_ptr, &info_ptr, png_infopp_NULL);

    GuacImage* img = (GuacImage*)lua_newuserdata(L, sizeof(GuacImage));
    img->surf = surf;
    img->prect = NULL;
    img->flags = 0;
    img->handle_x = img->handle_y = 0;

    return 1;
}
